#include "node.cpp"
#include <ext/hash_map>
using namespace std;
class table{
      __gnu_cxx::hash_map<int, node> db;
       
       //Remember to check if c and p exists.
       public: table(void){
            //db =  new __gnu_cxx::hash_map<int, node>();
       }
       //Insert
       void insert(node value, int id){
            db[id] = value;
            set<int> c = value.return_c();
            set<int> p = value.return_p();
            for(set<int>::iterator i=c.begin(); i!= c.end();i++){
                db[*i].add_p(id);
            }
            for(set<int>::iterator i=p.begin(); i!= p.end();i++){
                db[*i].add_c(id);
            }
       }
       void insert(node value){
            int max = 0;
            for(__gnu_cxx::hash_map<int, node>::iterator i = db.begin();i!=db.end();i++){
                 if(i->first>max){
                      max = i->first;                 
                 }             
            }
            insert(value, max+1);
       }
       //SELECT
       set<int> select_items(int id){
                set<int> result;
                result = db[id].return_i();                  
                return result;
       }
       set<int> select_items(set<int> id){
                set<int> result;
                set<int> tmp;
                for(set<int>::iterator c = id.begin(); c!=id.end(); c++){
                     tmp = db[*c].return_i();                  
                     result.insert(tmp.begin(),tmp.end());
                }
                return result;
       }
       node select_node(int id){
            return db[id];
       }
       
       
       //ALTER
       //Move a node
       void move(int id, int oldparent, int newparent){
            db[id].remove_p(oldparent);
            db[id].add_p(newparent);
       };
       void move(int id, set<int> oldparent, set<int> newparent){
            db[id].remove_p(oldparent);
            db[id].add_p(newparent);
       };
       //If a item exists in a subnode, then remove the supernode's item.
       void normalize_items(void){
            
       }
       //DELETE
       //currently it is full remove, need to make it support remove but item remain
       void remove(int id){
            for(__gnu_cxx::hash_map<int, node>::iterator i = db.begin();i!=db.end();i++){
                 db[i->first].remove_p(id);
                 db[i->first].remove_c(id);
            }
            db.erase(id);
       };
       void remove(set<int> id){
            for(__gnu_cxx::hash_map<int, node>::iterator i = db.begin();i!=db.end();i++){
                 db[i->first].remove_p(id);
                 db[i->first].remove_c(id);
            }
            for(set<int>::iterator c=id.begin();c!=id.end();c++){
                 db.erase(*c);
            }
       };
       
       //print
       void print(){
            for(__gnu_cxx::hash_map<int, node>::iterator i = db.begin();i!=db.end();i++){
                 cout<<i->first;
                 cout<<"\n";
                 db[i->first].print();
            }
       }
};
